<template>
  <div class="home">
        <!-- 数字人 -->
        <div  id="home"></div>
        <!-- 摄像头 -->
        <div class="video_canvas">
                <canvas ref="videoCanvas"></canvas>
                <!-- 显示接收到的文本 -->
                <!-- <div v-if="receivedText" class="text-message">
                  <p>{{ receivedText }}</p>
                </div> -->
        </div>
        <!-- 聊天对话框 -->
        <div class="chat_box">
                  <div ref="chatRef" class="caption_container_right ">
                    <div class="message_container" v-for="(item,index) in list" :key="index">
                                    <!-- 问题 -->
                                    <div v-if="item.type === 'question'"  :class=" item.type === 'question' ? 'flex_end':'' " class="message-item question">
                                          <div class="item-content box-shadow">
                                                  <div class="rich-text-card text-card">
                                                      <div class="content">
                                                        <pre>{{item.text}}</pre>
                                                      </div>
                                                    </div>
                                            </div>
                                            <div class="user-ico"></div>
                                    </div>
                                    <!-- 答案 -->
                                    <div v-if="item.type === 'answer'" class="message-item answer">
                                            <div class="user-ico"></div>
                                            <div class="item-content box-shadow">
                                                  <div class="rich-text-card text-card">
                                                          <div class="content">
                                                            <pre>{{item.text}}</pre>
                                                          </div>
                                                    </div>
                                            </div>
                                    </div>
                    </div>    
                   </div>
        </div>

    <div>

    </div>
    <!-- 输入框用于动态修改 WebSocket 地址 -->
    <!-- <div class="input">
      <input type="text" v-model="wsUrl"  placeholder="请输入 WebSocket 地址" />
      <button @click="updateWebSocket()" > 确认更换ws地址</button>
    </div> -->
  </div>
</template>

<script setup>
import {
  onMounted,
  ref,
} from 'vue';

import axios from 'axios';
import PCMPlayer from 'pcm-player'; // 导入 PCMPlayer 库

import { HwICSUiSdk } from '../utils/hwICSUiSdk';

const ws = ref(null);
const videoCanvas = ref(null);
let ctx = null;
let player = null;
const onceCode = ref(''); // 用于存储鉴权码
const receivedText = ref(''); // 用于存储接收到的文本
const wsUrl = ref('ws://192.168.100.148:10001'); // WebSocket 地址，绑定输入框

let tt;
const lockReconnect = ref(false); //避免重复连接
const SERVICE_ID_VIDEO = 10002;
const SERVICE_ID_AUDIO = 10001;

// 答案的响应式数据
const answerText = ref('');//阿里模型获取到的答案
const questionText = ref('');//完整的问题
const list = ref([]); //用来展示对话的数组
const chatRef = ref(null);
//  逐字展示demo
const streamList = ref(['首先需要避免暴饮暴食，尽量保持规律的饮食习惯，避免过度饥饿或过饱。', '其次，应避免摄入过多油腻食物和高脂肪食物，以免加重胰腺负担。', '此外，还应注意控制饮酒量，避免酒精对胰腺的损害。'])
const currIndex = ref(0)
const displayedText = ref('') // 正在显示的文字
let timer = null

onMounted(() => {
        ctx = videoCanvas.value.getContext('2d');
        initWebSocket(); // 初次连接 WebSocket
        axios.post('https://dyh.hangzhou.com.cn/api/v1/create-once-auth-code/acee8f79b36bd0785059581459d260de').then(res=>{
                          onceCode.value = res.data.data.once_code
                          }).then(()=>{
                                    HwICSUiSdk.create({
                                    serverAddress: 'metastudio-api.cn-north-4.myhuaweicloud.com',
                                    onceCode: onceCode.value,
                                    robotId: '2c9081859402aab6019416b26d720260',
                                    containerId: 'home',
                                    logLevel: 'debug',
                                    config: {
                                        // enableChatBtn: true,
                                        enableCaption: true,
                                        
                              },
                              eventListeners:{
                                                    jobInfoChange: (jobInfo) => {
                                                          console.info('jobInfoChange', jobInfo);
                                                          
                                                        },
                                                    speakingStart(){
                                                      console.log('开始说话')
                                                    },
                                                    speakingStop(){
                                                      console.log('本次说话结束了')
                                            
                                                    },
                                                    speechRecognized(){
                                                      console.log('33333333333')
                                                    },
                                    },
                              
        });
       })
  // 创建 PCMPlayer 实例
  player = new PCMPlayer({
    inputCodec: 'Int16',
    channels: 1, // 单声道
    sampleRate: 16000, // 确保与服务端一致
    flushTime: 0, // 音频刷新时间（根据需要调整）
  });
 

      // setInterval(() => {
      //         list.value.push({
      //       type: 'question',
      //       text: '大运河经过几个省份',
      //     })
      //       questionText.value = '大运河经过几个省份'
      //       getAnswer() }, 10000);
   
})

const startDisplayStr = () => {
  if (timer) {
    clearTimeout(timer)
  }
  // 将数组中的字符串拼接起来
  const res = streamList.value.join('')
  if (currIndex.value < res.length) {
    displayedText.value += res[currIndex.value]
    currIndex.value++
    setTimeout(startDisplayStr, 200)
  } else {
    clearTimeout(timer)
    timer = null
  }
}

// 列表内容自动顶格
const scroll_top = ( )=> {
  if(chatRef.value){
    chatRef.value.scrollTop = 99999999999;
  }  
}

// 将完整的问题推送到阿里 获取答案
const getAnswer = () => {
                 list.value.push({type: 'answer',text: '',})                          
                 var preStr = ''//保存切割后的最后一个数据
                 var start=false;
                 var evtSource = new EventSource('https://dyh.hangzhou.com.cn/api/v1/xwj-uq-ai?question=' + questionText.value+"&is_stream=1")
                       evtSource.addEventListener('message', function (e) {
                               var res = JSON.parse(e.data);
                               res.message  = res.message.replace(/\n/g,'')
                               if (res.status === 0) {
                                   HwICSUiSdk.sendDrivenText({ text: preStr, isLast: true });
                                   list.value.at(-1).text  += preStr;
                                  //  发送完毕 问题置空
                                   questionText.value = ''
                                   scroll_top()
                                   evtSource.close();
                                }
                                if (res.status === -1) {
                                    evtSource.close();
                                }  
                                if(res.status >-1) {
                                scroll_top()
                                      // 如过当前字符串中含有逗号则断句 反之保存
                                      if( res.message.includes('，')){
                                          let  resultArray = res.message.split('，');
                                          console.log('这是数组')
                                          console.log(resultArray)
                                          //将此次结果的第一项与上次的最后一项拼接 构建成新数组
                                            resultArray[0] = preStr + resultArray[0];
                                            // 最后一个数据保留与后面数据拼接 前面的所有数据推送
                                            for(let i=0;i<resultArray.length-1;i++){
                                                HwICSUiSdk.sendDrivenText({ text: resultArray[i], isLast: false });
                                                list.value.at(-1).text +=resultArray[i];
                                          }
                                                preStr = resultArray[resultArray.length-1];
                                      }else{
                                        preStr = preStr + res.message;
                                      }
                                 }
                });
}
// 更新 WebSocket 地址并重新连接
const updateWebSocket = () => {
  console.log('更新 WebSocket 地址:', wsUrl.value);
  
  if (ws.value) {
    ws.value.close(); // 关闭旧的 WebSocket 连接
  }else {
    console.log('重新连接ws');
    reconnect();
  }
};

// 开启 WebSocket 服务
const initWebSocket = () => {
  return new Promise((resolve, reject) => {
    const createWebSocket = () => {
      ws.value = new WebSocket(wsUrl.value);
      ws.value.onopen = () => {
        console.log(`WebSocket(${wsUrl.value})连接成功`);
        resolve();
      };
      ws.value.onmessage = onMessageHandler;
      ws.value.onerror = (error) => {
        console.error('WebSocket连接失败:', error);
        reconnect();
        reject(error);
      };
      ws.value.onclose = () => {
        console.log('WebSocket连接已关闭');
        reconnect();
      };
    };

    const reconnect = () => {
      if (lockReconnect.value) {
        return;
      }
      lockReconnect.value = true;
      if (ws.value.readyState === WebSocket.CLOSED) {
        tt && clearTimeout(tt);
        tt = setTimeout(() => {
          console.log("执行断线重连...");
          createWebSocket(); // 重新初始化 WebSocket
          lockReconnect.value = false;
        }, 4000);
      } else {
        console.log('WebSocket仍处于连接状态，不需要重新初始化。');
      }
    };

    createWebSocket();
  });
};

// 处理 WebSocket 消息
const onMessageHandler = (event) => {
  // console.log(event.data);
  if (typeof event.data === 'string') {
    try {
      const parsedData = JSON.parse(event.data);
      if (parsedData.data && parsedData.data.text && parsedData.data_type === 10003) {
          receivedText.value = parsedData.data.text;
          if(parsedData.type === 1){
              // 将问题推送到对话框中
              list.value.push({
                type: 'question',   
                text: receivedText.value,
              });
          }else{
            list.value.at(-1).text = receivedText.value;
            if(parsedData.type ===3){
              questionText.value = receivedText.value;
              getAnswer();
               scroll_top()
            }
          }
            
      }
   
    } catch (e) {
         console.log("消息不是有效的 JSON 格式，跳过...");
    }
  } else {
    if (event.data instanceof Blob) {
      event.data.arrayBuffer().then(handleMessage);
    } else if (event.data instanceof ArrayBuffer) {
      handleMessage(event.data);
    }
  }
};

const handleMessage = (arrayBuffer) => {
  const dataView = new DataView(arrayBuffer);
  const serviceId = dataView.getInt32(0, false);
  if (serviceId === SERVICE_ID_VIDEO) {
    handleVideoMessage(dataView);
  } else if (serviceId === SERVICE_ID_AUDIO) {
    handleAudioMessage(dataView);
  }
};

const handleAudioMessage = (dataView) => {
  console.log('音频数据', dataView);
  const dataLen = dataView.getInt32(4, false);
  const audioData = new Uint8Array(dataView.buffer, 8, dataLen);
  player.feed(audioData); // 使用 feed 方法播放音频数据
};

const handleVideoMessage = (dataView) => {
  const params = {
    width: dataView.getInt32(8, false),
    height: dataView.getInt32(12, false),
    faceX: dataView.getInt32(16, false),
    faceY: dataView.getInt32(20, false),
    faceW: dataView.getInt32(24, false),
    faceH: dataView.getInt32(28, false),
    isMouthOcc: dataView.getInt32(32, false),
    hasFace: dataView.getInt32(36, false)
  };
  const videoData = new Uint8Array(dataView.buffer, 40);
  displayVideo(videoData, params);
};

const displayVideo = (videoData, params) => {
  const width = params.width;
  const height = params.height;
  if (videoData.length !== width * height * 3) {
    console.error("Invalid video data length");
    return;
  }

  // 设置 canvas 的实际宽高
  videoCanvas.value.width = width;
  videoCanvas.value.height = height;

  const rgbaData = new Uint8ClampedArray(width * height * 4);
  for (let i = 0, j = 0; i < videoData.length; i += 3, j += 4) {
    rgbaData[j] = videoData[i + 2];
    rgbaData[j + 1] = videoData[i + 1];
    rgbaData[j + 2] = videoData[i];
    rgbaData[j + 3] = 255;
  }

  const imageData = new ImageData(rgbaData, width, height);
  ctx.putImageData(imageData, 0, 0);

  if (params.hasFace) {
    ctx.strokeStyle = 'green';
    ctx.lineWidth = 2;
    ctx.strokeRect(params.faceX, params.faceY, params.faceW, params.faceH);
    ctx.font = '20px Arial';
    ctx.fillStyle = 'green';
    ctx.fillText(params.isMouthOcc ? 'mask' : 'no mask', 10, 30);
    ctx.fillText(params.hasFace ? 'face' : 'no face', 10, 60);
  }
};
</script>

<style scoped>
@import './../utils/hwICSUiSdk/HwICSUiSdk.css';
.home {
  display: flex;
  position: relative;
}
canvas {
  width: 200px; /* 设置显示宽度为 300px */
  height: auto; /* 高度自动适应，保持宽高比 */
  display: block;
  margin: auto;
}
.input {
  margin-top: 20px;
}
.video_canvas{
  width: 200px;
  height: auto;
  border: 1px solid #ccc;
  position: absolute;
  z-index: 1000000;
  top: 0;
  right: 0;
}
.caption_container_right{
  align-self: flex-end;
  box-sizing: border-box;
  height: max-content;
  height: 540px;
  width: 960px;
  overflow: scroll;
}
.chat_box{
  position: absolute;
  top: 58%;
  left:calc(50% - 480px);
  z-index: 1000000;
  height: 640px;
  width: 960px;
  background: rgba(255, 255, 255, 0.3);
  border-radius: 60px;
  box-sizing: border-box;
  padding: 40px 0;
}
.caption_container_right >>>.message-item .question{
  display: flex !important;
  flex-direction: row !important;
  justify-content: flex-end !important;
  align-self: flex-end !important
}
.flex_end{
  justify-content: flex-end !important;
}
.message-item{
  width: 100% !important;
  display: flex;
    flex-shrink: 0;
    font-size: 16px;
    font-weight: 500;
    line-height: 24px;
    margin: 32px 40px !important;
    word-break: break-all;
    max-width: calc(100% - 80px);
  
}
.caption_container_right::-webkit-scrollbar {
  display: none; 
}
#home>>>.caption-container-hub {
  display: none !important; 
}
#home>>>.caption-portrait .message-container{
  display: none !important; 
}
.text-card .content pre {
  align-self: flex-start;
  margin: 0;
  max-width: 100%;
  text-align: left;
  white-space: pre-line;
}
pre {
  font-family: FZLTHJW,Helvetica Neue,Helvetica,Tahoma,Arial,Microsoft YaHei,PingFang SC,sans-serif;
}

.message-item.answer .item-content {
    border-radius: 0 16px 16px 16px;
}
.message-item .item-content {
    background-color: #fffc;
    max-height: 100%;
    max-width: 100%;
    padding: 12px 24px;
}
.message-item .user-ico {
  width: 100px !important;
  height: 100px !important;
}
.message-item .rich-text-card .content {
  font-size: 28px;
  line-height: 46px;
}
.box-shadow {
    box-shadow: 0 4px 20px -2px #00000014;
}
</style>
